package com.xym.web.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.xym.bean.TaotaoResult;

@Service
public class ApiService {
	@Value("${http.maxTotal}")
	private Integer maxTotal;

	@Value("${http.defaultMaxPerRoute}")
	private Integer defaultMaxPerRoute;

	@Value("${http.connectTimeout}")
	private Integer connectTimeout;

	@Value("${http.connectionRequestTimeout}")
	private Integer connectionRequestTimeout;

	@Value("${http.socketTimeout}")
	private Integer socketTimeout;

	@Value("${http.staleConnectionCheckEnabled}")
	private Boolean staleConnectionCheckEnabled;

	//下面接收
	private CloseableHttpClient httpClient;
	
	
	

	private IdleConnectionEvictor task;
	// PostConstruct注解标明该方法为初始化方法，会在对象构造函数执行完毕后执行
	@PostConstruct
	public void init() {
		// 构建连接池管理器对象
		PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
		// 设置最大连接数
		cm.setMaxTotal(maxTotal);
		// 设置每个主机地址的并发数
		cm.setDefaultMaxPerRoute(defaultMaxPerRoute);

		// 构建请求配置信息
		RequestConfig config = RequestConfig.custom()
				.setConnectTimeout(connectTimeout) // 创建连接的最长时间
				.setConnectionRequestTimeout(connectionRequestTimeout) // 从连接池中获取到连接的最长时间
				.setSocketTimeout(socketTimeout) // 数据传输的最长时间
				.setStaleConnectionCheckEnabled(staleConnectionCheckEnabled) // 提交请求前测试连接是否可用
				.build();

		// 构建HttpClient对象,把连接池、请求配置对象作为参数
		httpClient = HttpClients.custom().setConnectionManager(cm)
				.setDefaultRequestConfig(config).build();
		
		task = new IdleConnectionEvictor(cm);
		
		new Thread(task).start();
	}


	
	
	/**
	 * 参数为json的Post请求
	 * @param url
	 * @param jsonParam
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	public TaotaoResult doPostJson(String url,String jsonParam) throws ClientProtocolException, IOException{

        // 创建http POST请求   
        HttpPost httpPost = new HttpPost(url);
        StringEntity stringEntity = new StringEntity(jsonParam, ContentType.APPLICATION_JSON);
        // 将请求实体设置到httpPost对象中    设置post请求提交的表单
        httpPost.setEntity(stringEntity);
        //模拟了浏览器来进行访问  
        httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36");
       
        CloseableHttpResponse response = null;
        try {
            // 执行请求    敲回车
            response = httpClient.execute(httpPost);
            // 将响应状态码交给调用者自行判断  返回响应状态码和数据
            int statusCode = response.getStatusLine().getStatusCode();
            String data = EntityUtils.toString(response.getEntity(), "UTF-8");
            return TaotaoResult.build(statusCode, data);
        } finally {
            if (response != null) {
                response.close();
            }
         }
        }
	
	
	
	/**
	 * 无参的get请求
	 */
	public String doGet(String uri) throws IOException {
		// 创建HttpGet请求，相当于在浏览器输入地址
		HttpGet httpGet = new HttpGet(uri);

		CloseableHttpResponse response = null;
		try {
			// 执行请求，相当于敲完地址后按下回车。获取响应
			response = httpClient.execute(httpGet);
			// 判断返回状态是否为200
			if (response.getStatusLine().getStatusCode() == 200) {
				// 解析响应，获取数据
				return EntityUtils.toString(response.getEntity(), "UTF-8");
			}
		} finally {
			if (response != null) {
				response.close();
			}
		}
		return null;
	}

	/**
	 * 有参get请求
	 */
	public String doGet(String uri, Map<String, String> params)
			throws Exception {
		// 创建地址构建器
		URIBuilder builder = new URIBuilder(uri);
		// 拼接参数
		for (Map.Entry<String, String> me : params.entrySet()) {
			builder.addParameter(me.getKey(), me.getValue());
		}
		return doGet(builder.build().toString());

	}

	/**
	 * 有参POST请求
	 */
	public String doPost(String uri, Map<String, String> params)
			throws Exception {
		// 创建http POST请求
		HttpPost httpPost = new HttpPost(uri);
		httpPost.setHeader(
				"User-Agent",
				"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36");
		if (params != null) {
			// 设置参数
			List<NameValuePair> parameters = new ArrayList<NameValuePair>(0);
			for (Map.Entry<String, String> me : params.entrySet()) {
				parameters.add(new BasicNameValuePair(me.getKey(), me
						.getValue()));
			}
			// 构造一个form表单式的实体
			UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(
					parameters);
			// 将请求实体设置到httpPost对象中
			httpPost.setEntity(formEntity);
		}

		CloseableHttpResponse response = null;
		try {
			// 执行请求
			response = httpClient.execute(httpPost);
			// 判断返回状态是否为200
			if (response.getStatusLine().getStatusCode() == 200) {
				String content = EntityUtils.toString(response.getEntity(),
						"UTF-8");
				System.out.println(content);
			}
		} finally {
			if (response != null) {
				response.close();
			}
		}
		return null;
	}

	/**
	 * 无参POST请求
	 * 
	 * @throws Exception
	 */
	public String doPost(String uri) throws Exception {
		return doPost(uri, null);
	}

	/**
	 * 内部类 实现Runnable接口，成为线程任务类
	 * 
	 * @author Administrator
	 *
	 */
	class IdleConnectionEvictor implements Runnable {

		private final HttpClientConnectionManager connMgr;

		private volatile boolean shutdown;

		public IdleConnectionEvictor(HttpClientConnectionManager connMgr) {
			this.connMgr = connMgr;
		}

		// 定义线程任务，定时关闭失效的连接
		@Override
		public void run() {
			try {
				while (!shutdown) {
					synchronized (this) {
						// 每隔5秒钟一次
						wait(50000);
						// 关闭失效的连接
						connMgr.closeExpiredConnections();
					}
				}
			} catch (InterruptedException ex) {
				// 结束
			}
		}

		public void shutdown() {
			shutdown = true;
			synchronized (this) {
				notifyAll();
				System.out.println("定时清理任务即将结束。。");
			}
		}

		@PreDestroy
		public void destory() throws IOException{
			task.shutdown();
			httpClient.close();
		}

	}
}
